import { Context } from 'koa';
import { AppContext } from '@/types';
import { Department, Company } from '@/models';
import * as response from '@/utils/response';
import { validate, commonSchemas } from '@/utils/validator';
import logger from '@/utils/logger';
import Joi from 'joi';
import { Op } from 'sequelize';

/**
 * 部门管理控制器
 */
class DepartmentController {
  /**
   * 获取部门列表
   */
  async list(ctx: Context) {
    const appCtx = ctx as AppContext;

    // 验证参数
    const schema = Joi.object({
      page: commonSchemas.page,
      pageSize: commonSchemas.pageSize,
      name: Joi.string().allow('').optional(),
      companyId: Joi.string().uuid().allow('').optional(),
      status: Joi.string().valid('active', 'inactive').allow('').optional(),
    });

    const params = await validate<any>(
      {
        page: ctx.query.page,
        pageSize: ctx.query.pageSize,
        name: ctx.query.name,
        companyId: ctx.query.companyId,
        status: ctx.query.status,
      },
      schema
    );

    const { page = 1, pageSize = 20, name, companyId, status } = params;

    try {
      // 构建查询条件
      const where: any = {
        tenantId: appCtx.state.user!.tenantId,
      };

      if (name) {
        where.name = { [Op.like]: `%${name}%` };
      }
      if (companyId) {
        where.companyId = companyId;
      }
      if (status) {
        where.status = status;
      }

      // 查询数据
      const { rows, count } = await Department.findAndCountAll({
        where,
        include: [
          {
            model: Company,
            as: 'company',
            attributes: ['id', 'name', 'code'],
          },
        ],
        limit: pageSize,
        offset: (page - 1) * pageSize,
        order: [['createdAt', 'DESC']],
      });

      response.paginated(ctx, rows, count, page, pageSize);
    } catch (error) {
      logger.error('获取部门列表失败:', error);
      ctx.throw(500, '获取部门列表失败');
    }
  }

  /**
   * 获取部门详情
   */
  async get(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { id } = ctx.params;

    try {
      const department = await Department.findOne({
        where: {
          id,
          tenantId: appCtx.state.user!.tenantId,
        },
        include: [
          {
            model: Company,
            as: 'company',
            attributes: ['id', 'name', 'code'],
          },
        ],
      });

      if (!department) {
        return response.error(ctx, '部门不存在', 404);
      }

      response.success(ctx, department);
    } catch (error) {
      logger.error('获取部门详情失败:', error);
      ctx.throw(500, '获取部门详情失败');
    }
  }

  /**
   * 创建部门
   */
  async create(ctx: Context) {
    const appCtx = ctx as AppContext;

    // 验证参数
    const schema = Joi.object({
      name: Joi.string().required(),
      companyId: Joi.string().uuid().required(),
      parentId: Joi.string().uuid().allow(null).optional(),
      description: Joi.string().optional().allow(''),
      status: Joi.string().valid('active', 'inactive').default('active'),
    });

    const data = await validate<any>(ctx.request.body as any, schema);

    try {
      // 检查公司是否存在
      const company = await Company.findOne({
        where: {
          id: data.companyId,
          tenantId: appCtx.state.user!.tenantId,
        },
      });

      if (!company) {
        return response.error(ctx, '公司不存在', 400);
      }

      // 检查部门名称是否已存在（同一公司下）
      const existingDepartment = await Department.findOne({
        where: {
          tenantId: appCtx.state.user!.tenantId,
          companyId: data.companyId,
          name: data.name,
        },
      });

      if (existingDepartment) {
        return response.error(ctx, '部门名称已存在', 400);
      }

      // 如果有父部门，检查是否存在
      if (data.parentId) {
        const parentDepartment = await Department.findOne({
          where: {
            id: data.parentId,
            tenantId: appCtx.state.user!.tenantId,
            companyId: data.companyId,
          },
        });

        if (!parentDepartment) {
          return response.error(ctx, '父部门不存在', 400);
        }
      }

      // 创建部门
      const department = await Department.create({
        ...data,
        tenantId: appCtx.state.user!.tenantId,
      });

      logger.info(`部门创建成功: ${department.name} by ${appCtx.state.user!.email}`);
      ctx.status = 201;
      response.success(ctx, department, '部门创建成功');
    } catch (error) {
      logger.error('创建部门失败:', error);
      ctx.throw(500, '创建部门失败');
    }
  }

  /**
   * 更新部门
   */
  async update(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { id } = ctx.params;

    // 验证参数
    const schema = Joi.object({
      name: Joi.string().optional(),
      companyId: Joi.string().uuid().optional(),
      parentId: Joi.string().uuid().allow(null).optional(),
      description: Joi.string().optional().allow(''),
      status: Joi.string().valid('active', 'inactive').optional(),
    });

    const data = await validate<any>(ctx.request.body as any, schema);

    try {
      const department = await Department.findOne({
        where: {
          id,
          tenantId: appCtx.state.user!.tenantId,
        },
      });

      if (!department) {
        return response.error(ctx, '部门不存在', 404);
      }

      // 如果更新公司，检查公司是否存在
      if (data.companyId && data.companyId !== department.companyId) {
        const company = await Company.findOne({
          where: {
            id: data.companyId,
            tenantId: appCtx.state.user!.tenantId,
          },
        });

        if (!company) {
          return response.error(ctx, '公司不存在', 400);
        }
      }

      // 检查名称是否已存在
      if (data.name && data.name !== department.name) {
        const existingDepartment = await Department.findOne({
          where: {
            tenantId: appCtx.state.user!.tenantId,
            companyId: data.companyId || department.companyId,
            name: data.name,
            id: { [Op.ne]: id },
          },
        });

        if (existingDepartment) {
          return response.error(ctx, '部门名称已存在', 400);
        }
      }

      // 如果更新父部门，检查是否存在且不能是自己
      if (data.parentId) {
        if (data.parentId === id) {
          return response.error(ctx, '父部门不能是自己', 400);
        }

        const parentDepartment = await Department.findOne({
          where: {
            id: data.parentId,
            tenantId: appCtx.state.user!.tenantId,
            companyId: data.companyId || department.companyId,
          },
        });

        if (!parentDepartment) {
          return response.error(ctx, '父部门不存在', 400);
        }
      }

      // 更新部门
      await department.update(data);

      logger.info(`部门更新成功: ${department.name} by ${appCtx.state.user!.email}`);
      response.success(ctx, department, '部门更新成功');
    } catch (error) {
      logger.error('更新部门失败:', error);
      ctx.throw(500, '更新部门失败');
    }
  }

  /**
   * 删除部门
   */
  async delete(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { id } = ctx.params;

    try {
      const department = await Department.findOne({
        where: {
          id,
          tenantId: appCtx.state.user!.tenantId,
        },
      });

      if (!department) {
        return response.error(ctx, '部门不存在', 404);
      }

      // 检查是否有子部门
      const childDepartments = await Department.count({
        where: {
          parentId: id,
          tenantId: appCtx.state.user!.tenantId,
        },
      });

      if (childDepartments > 0) {
        return response.error(ctx, '该部门下存在子部门，无法删除', 400);
      }

      await department.destroy();

      logger.info(`部门删除成功: ${department.name} by ${appCtx.state.user!.email}`);
      response.success(ctx, null, '部门删除成功');
    } catch (error) {
      logger.error('删除部门失败:', error);
      ctx.throw(500, '删除部门失败');
    }
  }
}

export default new DepartmentController();

